package com.huang.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huang.entity.User;
import com.huang.service.UserService;
import com.huang.util.ErrorCode;
import com.huang.util.JwtUtil;
import com.huang.util.Result;
import com.huang.vo.UserVo;
import com.huang.vo.param.LoginParams;
import com.huang.vo.param.RegisterParams;
import lombok.Data;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author hmj
 * @since 2021-10-09
 */
@Data
@RestController //代表返回JSON数据
@RequestMapping("user")  //总路由地址
public class UserController {

    //MD5加密盐值
    @Value("${huang.md5.salt}")
    private String salt;

    @Autowired
    UserService userService;

    //redis
    @Autowired
    RedisTemplate<String, String> redisTemplate;

    //Jwt工具类
    @Autowired
    JwtUtil jwtUtil;

    /*
     *获取前端传递参数的几种方法
     * 1. 前端请求为path?id=1 可通过@RequestParam("id") int id获得
     * 2. 前端请求为path/{id} 可通过@PathVariable("id") int id获得
     * 3. 前台传递的为json数据 可通过@RequestBody User user获得
     * 4. 还有@RequestHeader获取请求头数据
     * */
    @PostMapping("/login")
    public Result login(@RequestBody LoginParams loginParams) {
        /*
         * 登陆的逻辑
         * 1.判断传递过来的参数是否都不为空
         * 2.在数据库中查询是否有该用户
         * 3.如果有该用户就生成token返回并存入redis
         * */
        String account = loginParams.getAccount();
        String password = loginParams.getPassword();
        if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) {
            return Result.fail(ErrorCode.PARAM_ERROR.getCode(), ErrorCode.PARAM_ERROR.getMsg());
        }
        //对密码进行MD5加密,查询该用户并判断是否存在
        String s = DigestUtils.md5Hex(password + salt);
        //等价于 SELECT * FROM td_user WHERE ACCOUNT=#{account} AND PASSWORD=#{password} limit 1;
        User user = userService.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getAccount, account)
                .eq(User::getPassword, s)
                .last("limit 1"));
        if (user == null) {
            return Result.fail(ErrorCode.ACCOUNT_OR_PASSWORD_NOT_EXIST.getCode(), ErrorCode.ACCOUNT_OR_PASSWORD_NOT_EXIST.getMsg());
        }
        //登录成功，使用JWT生成token，返回token和redis中
        String token = jwtUtil.createToken(user.getId());
        redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(user), 6, TimeUnit.HOURS);
        return Result.success(token);
    }

    @PostMapping("/register")
    public Result register(@RequestBody RegisterParams registerParams) {
        /*
         * 注册逻辑
         * 1.判断传递过来的参数是否完全
         * 2.判断是否账户名重复
         * 3.没有该用户就将其insert到数据库
         * 4.生成token存入redis,并返回给前端
         * */
        String account = registerParams.getAccount();
        String password = registerParams.getPassword();
        String nickname = registerParams.getNickName();
        if (StringUtils.isBlank(account) || StringUtils.isBlank(password) || StringUtils.isBlank(nickname)) {
            return Result.fail(ErrorCode.REGISTER_ERROR.getCode(), ErrorCode.REGISTER_ERROR.getMsg());
        }
        //根据用户名查询用户
        User user = userService.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getAccount, account)
                .last("limit 1"));
        if (user != null) {
            return Result.fail(ErrorCode.REPEAT_REGISTER.getCode(), ErrorCode.REPEAT_REGISTER.getMsg());
        }
        //设置用户信息并insert到数据库
        user = new User();
        user.setAccount(account);
        user.setPassword(DigestUtils.md5Hex(password + salt));
        user.setNickname(nickname);
        userService.save(user);
        String token = jwtUtil.createToken(user.getId());
        redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(user), 6, TimeUnit.HOURS);
        return Result.success(token);
    }

    @GetMapping("/currentUser")
    public Result currentUser(@RequestHeader("Authorization") String token) {
        /*
         * 获取当前用户的逻辑
         * 1.判断token是否为空
         * 2.在redis中查询该token对应的值是否存在
         * 3.返回用户信息
         * */
        if (token == null) {
            return Result.fail(ErrorCode.NO_LOGIN.getCode(), ErrorCode.NO_LOGIN.getMsg());
        }
        String s = jwtUtil.getClaimByToken(token).getSubject();
        if (s == null) {
            return Result.fail(ErrorCode.NO_LOGIN.getCode(), ErrorCode.NO_LOGIN.getMsg());
        }
        String userJson = redisTemplate.opsForValue().get("TOKEN_" + token);
        if (userJson == null) {
            return Result.fail(ErrorCode.NO_LOGIN.getCode(), ErrorCode.NO_LOGIN.getMsg());
        }
        User user = JSON.parseObject(userJson, User.class);
        UserVo userVo = new UserVo();
        userVo.setAccount(user.getAccount());
        userVo.setNickName(user.getNickname());
        userVo.setId(user.getId());
        System.out.println(user.getId());
        return Result.success(userVo);
    }

    @GetMapping("/logout")
    public Result logout(@RequestHeader("Authorization") String token) {
        redisTemplate.delete("TOKEN_" + token);
        return Result.success("登出成功",null);
    }

    @GetMapping("/test")
    public Result test() {
        return Result.success("测试成功",null);
    }
}
